pub fn learn_thread() {
  //_learn_thread_spawn();
  _learn_thread_join();
}

// 线程问题:
// 竟态条件:多个线程以不一致的顺序访问数据或资源
// 死锁: 两个线程相互等待对方,这会阻止两者继续运行
// 只会发送在特定情况且难以稳定重现和修复的bug

// 使用spawn创建新线程
use std::thread;
use std::time::Duration;

fn _learn_thread_spawn() {
  thread::spawn(|| {
    for i in 1..=10 {
      println!("hi number {} from the spawned thread!", i);
      thread::sleep(Duration::from_millis(1));
    }
  });

  for i in 1..=5 {
    println!("hi number {} from the main thread!", i);
    thread::sleep(Duration::from_millis(1));
  }
}

// 使用join等待所有线程结束
fn _learn_thread_join() {
  let handle = thread::spawn(|| {
    for i in 1..=10 {
      println!("hi number {} from the spawned thread!", i);
      thread::sleep(Duration::from_millis(1));
    }
  });
  // 主线程等待handle中的所有子线程执行完毕,才继续往下执行,此时就不会
  // 出现多个线程(主线程和spawn出的子线程)交替执行的情况
  handle.join().unwrap();

  for i in 1..=5 {
    println!("hi number {} from the main thread!", i);
    thread::sleep(Duration::from_millis(1));
  }
  // 主线程与子线程交替执行,主线程执行完毕后,等待所有join的子线程执行完毕
  //handle.join().unwrap();
}

// 将move闭包与线程一同使用
fn _learn_thread_move0() {
  let v = vec![1, 2, 3];
  // 因此需要拿到被捕获的数据的所有权
  let handle = thread::spawn(move || {
    // println!只需要v的引用,闭包尝试借用v.
    // 但有个问题,rust不知道这个新线程会执行多久,所以无法知道v的引用是否一直有效
    println!("Here's a vector: {:?}", v);
  });
  // 比如在这里drop了v,下面的handle.join执行时就会使用一个无效的v
  // 在加了move后,这里无法drop,因为drop也需要v的所有权
  // drop(v);

  handle.join().unwrap();
}
